Notes on Pokémon Red/Green/Blue/Yellow Music Conversion to AGB
by RichterSnipes

Disclaimer
I do not guarantee or claim that these values are absolutely correct. They are just things that I have observed in my hacking.

Both "AGB" and "Sappy" have been used as names for Nintendo's primary sound engine on the Game Boy Advance.
Sappy is also the name of a program used to play and edit music from GBA games using that sound engine.
To avoid confusion, I'll refer to the program as Sappy and the sound engine as AGB.

This documents my findings and observations in comparing the music structure of the Gen. 1 Pokémon games and Nintendo's AGB sound engine for GBA games.
To listen to tracks properly, do so in an emulator or on actual hardware. Sappy has enough inaccuracies in music playback - especially with the PSG - to make it not ideal.
I personally use the latest MFC-based version of VBA-M strictly for sound playback; the WX version of VBA-M is incredibly buggy.
mGBA sound playback appears to be less developed, particulary in terms of the PSG. However, I don't know which of the two is actually more accurate in that department. I don't have access to a GBA flashcart.
Most things that the Gen. 1 games do in music terms can be natively supported in AGB with PSG audio channels. Anything else would require a different sound engine with the feature specifically built in.

Volume:

All instruments use the same volume. Set volume to the max level (127) in the AGB soundfont.
Gen. 1 games have volume set as F0 77 in hex. Changing this value doesn't do anything.

Instrument traits:

Tempo:
	ED xx xx
	
In AGB, a tempo of 240 makes each whole note (96/96ths) last one second.
Tempos are calculated differently between the Gen. 1 games and AGB. Use the following formulas:
	Gen. 1 combined speed = tempo * highest used note speed
	AGB Tempo = 230400/(Gen. 1 combined speed)
Multiply notes in a specific the PSG audio channel in AGB by (channel's current note speed)/(highest used note speed)
	
The only way to get true range of note lengths would be if notes in AGB could reach up to 192 in length. They only go up to 96. Modify songs on a per-song basis to work around this.

Duty:
	EC xx

	xx: This determines the "duty" of square waves.
		00 - 12.5%
		01 - 25%
		02 - 50%
		03 - 75%

Modulation:
	EA xx yz

	x: This value represents modulation delay.
		MPlayDef - LFODL
		In Gen. 1 games, it is independent of tempo and note speed. An approximation of delay in seconds is this:
		delay in seconds = (decimal conversion of xx * (5/3))/100 
		It's tied to tempo in AGB. LFODL is equal to how many 96ths of a note modulation is delayed. This is the conversion formula. Be sure to round:
		LFODL = (AGB tempo/240) * delay in seconds * 96
		      = decimal conversion of xx * AGB tempo * 2/300
	y: This value represents modulation depth.
		MPlayDef - MOD
		Just take y for the calculation. This seems to work most of the time.
		It seems that modulation has less of an effect on lower-pitched notes in Gen. 1 games.
	z: This value represents modulation speed.
		MPlayDef - LFOS
		Like delay, modulation is independent of tempo in Gen. 1 games. 
		z = 0 acts as maximum modulation speed. Speed decreases as z increases.
		I have no way of calculating this due to odd (exponential?) scaling on the Gen. 1 side and inconsistency on the AGB side.

Modulation as a whole differs between the Gen. 1 games and in the Sappy format.
The vibrato only hits the standard note and depth note in the Gen. 1 games, like alternating between frets on a guitar.
It hits that depth both above and below the note, and everything in between in AGB with a sine wave pattern.
Although this can be replicated with PSG channels using constant note bending, it's incredibly unreasonable.
That apparently didn't stop whoever coded the music for FireRed/LeafGreen, though. Except it constantly switehes MOD on and off instead, giving kind of a similar result.
It hitches when changing notes in the middle of a vibrato in Gen. 1 games, making the track off pitch for a fraction of a second.
In general, LFOS behaves oddly with PSG channels. It's inconsistent across various platforms. There may be some undocumented feature of it that few people - if any - are aware of.
	
Velocity - Square Waves:
	Dx yz

	x: This identifies note speed. It goes up to 12 (A in hex).
		Unlike tempo, note speed affects modulation.
	y: This is the velocity of the track.
		In AGB, this value is set in the track itself.
		The following equation (y + 1) * 8 signifies velocity within the track (v???).
		A y value of F will correspond to velocity of v127.
	z: This is the length of note hold.
		In AGB, this value is set per voice.
		This is what the number "Dec" should be for the currently playing voice.

Notes rise in velocity when y, in hex, is anywhere from 9 to F (8 behaves like 0). Each successive value slows down the rate of the rise.
Make sure to add a multiple of 16 to the decimal form of y for rises, otherwise the note will cut off at the point that a fade would at the given velocity.

Gen. 2 games also have a function that does similar to velocity, but skips the note speed part.

Velocity - Triangle Wave:
	Dx yz
	
	x: This identifies note speed. It goes up to 12 (A in hex).
	y: This value does the following depending on what it equals:
		1: v127
		2: v080
		3: v040
		All other values will result in 0 velocity and will likely not be used.
	z: This selects the wave pattern used. 
		Wave patterns are stored in RAM at 0xFF30 and defined in the ROM.

Noise Instruments:
Noise instruments are predetermined for each of the Game Boy (Color) Pokémon games.
These definitions are found just after the music bank headers for each game:

	2x Yy Zz

The first value always begins with a 2 to signify a new noise sample.
	x = delay before next note is played; used for multi-notes
	Y = velocity
	y = decay
	Zz = note; doesn't seem to follow exact patterns, so requires observation

The Gen. 2 games include all the noise patterns from the Gen. 1 games. The noise patterns used exclusively in those games are defined after them.

Pitch Bending:
	EB 00 yz
	
	y = octave; refer to the octaves table below to see what the y corresponds to
	z = note; refer to the notes table below to see what the z corresponds to
	
The Gen. 1 games handle pitch bending with a single command. It hits key notes similar to how AGB manually bends to specific steps. 
Pitches don't always bend on the note length you tell them to in AGB. Either this is a bug with the engine or a bug with emulation.
It doesn't even make the same sound consistently ingame. It must have something to do with internal timings.
BENDR = up to how many notes in one direction a note can bend.
BEND = how much to bend, but it seems to behave unpredicatbly at points. I'm not sure if that's how it's supposed to be or if it's due to emulation errors.

Octaves
E0: Octave 8
E1: Octave 7
E2: Octave 6
E3: Octave 5
E4: Octave 4
E5: Octave 3
E6: Octave 2
E7: Octave 1

Notes
0: C
1: C#
2: D
3: D#
4: E
5: F
6: F#
7: G
8: G#
9: A
A: A#
B: B
C: Rest

Note Length
Each hex value corresponds to a sixteenth of a note.
0 lasts for 1/16 of a note, while F lasts for a full note.

Panning:

1st-Gen songs utilize a panning type that simulates watching a band performance. The main sound and noise instrument are centered, accompaniment is on left, and bass is on right.
2nd-Gen songs keep the same panning they had in their original games.
Battle tracks have no panning so that Pokémon cries and attacks can remain the sole focus of stereo separation.

Perfect Pitch:

Value E8 is enabled for the majority of instances of the Square Wave 1 channel in the Gen. 1 games.
This enables perfect pitch, which lessens instrument distortion.
It's useful when the two channels play sounds that are nearly the same.
It's also erroneously enabled on the triangle wave used in one of the city tunes.
Sappy refers to this as "note off with noise."

Duty Shifting:
	FC xx
	
Duty shifting is used to rapidly change the sound being emitted from a square wave channel. It causes the square wave to quickly switch between all four duty cycles.
Duty shifting is a custom feature of the Gen. 1 sound engine and engines in other specific NES/GB(C) games, and is not supported in AGB. It's also unfeasible with other tactics.
Tracks using this will need to be avoided, considerably altered, or played back as a sample wholesale if porting to a game using the AGB sound engine.
